import React, { StrictMode, useState, useRef, useImperativeHandle, useContext } from 'react'
import { useSelector, useDispatch } from "react-redux"
const boxStyle = {
  margin: '10px',
  border: '1px solid #ccc',
  borderRadius: '10px',
  padding: '10px',
}

// +++++++++++++++++++++++++++++ 科里化函数 +++++++++++++++++++++++++++++++++
// 函数柯里化封装（这个封装可以直接复制走使用）
// 初始化时可以添加部分参数
function curry(fn, args) {
  // length为定义fn时的函数参数
  var length = fn.length;
  console.log(11111,args)
  var args = args || [];
  // arguments为函数产生 类数组
  return function () {
      let newArgs = args.concat(Array.prototype.slice.call(arguments));
      if (newArgs.length < length) {
          return curry.call(this, fn, newArgs);
      } else {
          return fn.apply(this, newArgs);
      }
  }
}

//需要被柯里化的函数
function multiFn(a, b, c) {
  return a * b * c;
}

//multi是柯里化之后的函数
var multi = curry(multiFn);
console.log(multi(2)(3)(4));
// console.log(multi(2, 3, 4));
// console.log(multi(2)(3, 4));
// console.log(multi(2, 3)(4));

// +++++++++++++++++++++++++++++ 科里化函数 收集展开优化 +++++++++++++++++++++++++++++++++
// 支持科里化时传参
function curry1(fn, ...args) {
  var length = fn.length;
  console.log(11111,args)
  var args = args || [];
  return function () {
      let newArgs = args.concat(Array.prototype.slice.call(arguments));
      if (newArgs.length < length) {
          return curry1.call(this, fn, ...newArgs);
      } else {
          return fn.apply(this, newArgs);
      }
  }
}
function multiFn1(a, b, c) {
  return a * b * c;
}

var multi1 = curry1(multiFn1, 3, 4);
console.log(2222222, multi1(5))
console.log(2222222, curry1(multiFn1)(3,4,5))
console.log(2222222, curry1(multiFn1, 3)(4,5))
console.log(2222222, curry1(multiFn1, 3,4,5)())

// +++++++++++++++++++++++++++++ 中间件实现 尝试 #1：手动打日志 +++++++++++++++++++++++++++++++++
// const action = addTodo('Use Redux')
// console.log('dispatching', action)
// store.dispatch(action)
// console.log('next state', store.getState())

// +++++++++++++++++++++++++++++ 中间件实现 尝试 # 封装 dispatch +++++++++++++++++++++++++++++++++
// function dispatchAndLog(store, action) {
//   console.log('dispatching', action)
//   store.dispatch(action)
//   console.log('next state', store.getState())
// }
// dispatchAndLog(store, addTodo('Use Redux'))

// +++++++++++++++++++++++++++++ 中间件实现 尝试 # 给 dispatch 做猴子补丁（Monkeypatch） +++++++++++++++++++++++++++++++++
// 获取原有 store.dispatch next, 封装函数中使用, 并且返回 修改next
// 再执行store.dispatch时, 会先执行我们外部中间件, 最后进入store的dispatch方法
// const next = store.dispatch
// store.dispatch = function dispatchAndLog(action) {
//   console.log('dispatching', action)
//   let result = next(action)
//   console.log('next state', store.getState())
//   return result
// }

//  问题多个中间件 手动调用
// function patchStoreToAddLogging(store) {
//   const next = store.dispatch
//   store.dispatch = function dispatchAndLog(action) {
//     console.log('dispatching', action)
//     let result = next(action)
//     console.log('next state', store.getState())
//     return result
//   }
// }

// function patchStoreToAddCrashReporting(store) {
//   const next = store.dispatch
//   store.dispatch = function dispatchAndReportErrors(action) {
//     try {
//       return next(action)
//     } catch (err) {
//       console.error('Caught an exception!', err)
//       Raven.captureException(err, {
//         extra: {
//           action,
//           state: store.getState()
//         }
//       })
//       throw err
//     }
//   }
// }
// patchStoreToAddLogging(store)
// patchStoreToAddCrashReporting(store)

// +++++++++++++++++++++++++++++ 中间件实现 尝试 #4. 隐藏猴子补丁 +++++++++++++++++++++++++++++++++
// function logger(store) {
//   const next = store.dispatch
//   // 之前:
//   // store.dispatch = function dispatchAndLog(action) {
//   return function dispatchAndLog(action) {
//     console.log('dispatching', action)
//     let result = next(action)
//     console.log('next state', store.getState())
//     return result
//   }
// }

// function applyMiddlewareByMonkeypatching(store, middlewares) {
//   middlewares = middlewares.slice()
//   middlewares.reverse()

//   // 依次调用每个 middleware 来增强 dispatch
//   middlewares.forEach(middleware => (store.dispatch = middleware(store)))
// }
// applyMiddlewareByMonkeypatching(store, [logger, crashReporter])

// +++++++++++++++++++++++++++++ 中间件实现 尝试 #5. 移除猴子补丁 +++++++++++++++++++++++++++++++++
// 前面写法需要手动 修改store.dispatch
// 使用ES6 箭头函数科里化,传入 store 和 next, 简化流程
// const logger = store => next => action => {
//   console.log('dispatching', action)
//   let result = next(action)
//   console.log('next state', store.getState())
//   return result
// }

// const crashReporter = store => next => action => {
//   try {
//     return next(action)
//   } catch (err) {
//     console.error('Caught an exception!', err)
//     Raven.captureException(err, {
//       extra: {
//         action,
//         state: store.getState()
//       }
//     })
//     throw err
//   }
// } 

// 注意：这是简单粗暴的middleware调用方法
// 并 *不是* Redux API 真实的实现方法。
// function applyMiddleware(store, middlewares) {
//   middlewares = middlewares.slice()
//   middlewares.reverse()
//   let dispatch = store.dispatch
//   middlewares.forEach(middleware => (dispatch = middleware(store)(dispatch)))
//   return Object.assign({}, store, { dispatch })
// }


export class CurryTemplate extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      str: '单层使用conText',
      name: 'Guest',
      userProvide: { password: '232323' },
    }

    this.handleChange = (event) => {
      this.setState({ name: event.target.value })
    }
  }
  componentDidMount() {
    console.log('conTextTemplate...')

  }
  render() {
    return (
        <div style={boxStyle}>
          <p>函数柯里化...及redux中间件实现过程</p>
        </div>
    )
  }
}
